package xyz.wbsite.dbtool.javafx;

import javafx.application.Application;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.ChoiceBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.image.Image;
import javafx.scene.input.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Callback;
import javafx.util.converter.DefaultStringConverter;
import javafx.util.converter.IntegerStringConverter;
import xyz.wbsite.dbtool.javafx.ctrl.DetailModuleController;
import xyz.wbsite.dbtool.javafx.ctrl.DetailProjectController;
import xyz.wbsite.dbtool.javafx.ctrl.DetailTableController;
import xyz.wbsite.dbtool.javafx.ctrl.MainController;
import xyz.wbsite.dbtool.javafx.manger.ManagerFactory;
import xyz.wbsite.dbtool.javafx.manger.ProjectManager;
import xyz.wbsite.dbtool.javafx.po.*;
import xyz.wbsite.dbtool.javafx.tool.ContextMenuBuilder;
import xyz.wbsite.dbtool.javafx.tool.Dialog;
import xyz.wbsite.dbtool.javafx.tool.Tool;
import xyz.wbsite.dbtool.javafx.view.DBCheckBoxTableCell;
import xyz.wbsite.dbtool.javafx.tool.ResourceUtil;

import java.net.URL;
import java.util.*;

public class JavaFxApplication extends Application {

    private ProjectManager projectManager = ManagerFactory.getProjectManager();
    private TreeView mTree = null;
    private Pane mDetail = null;
    private TableView mFields = null;
    private Button add = null;
    private Button sub = null;
    private FXMLLoader mMainLoader;
    private FXMLLoader mProjectLoader;
    private FXMLLoader mModuleLoader;
    private FXMLLoader mTableLoader;
    private MainController mainController;
    private DetailProjectController detailProjectController;
    private DetailModuleController detailModuleController;
    private DetailTableController detailTableController;
    private Project currentProject;
    private Module currentModule;
    private Table currentTable;
    private boolean dragMD = false;
    public static Stage primaryStage;

    @Override
    public void start(Stage primaryStage) throws Exception {
        JavaFxApplication.primaryStage = primaryStage;
        BorderPane root = mMainLoader.getRoot();

        primaryStage.setTitle("DBtool");
        primaryStage.setMinWidth(765 + 45);
        primaryStage.setMinHeight(550 + 40);
        primaryStage.setScene(new Scene(root));
        primaryStage.centerOnScreen();
        primaryStage.show();
        primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent event) {
                primaryStage.close();
                System.exit(0);
            }
        });
        primaryStage.getIcons().add(new Image(ResourceUtil.getInput("icon.png")));
    }

    @Override
    public void init() throws Exception {
        URL main = ResourceUtil.getURL("classpath:fxml/main.fxml");
        mMainLoader = new FXMLLoader(main);
        mMainLoader.load();
        mainController = mMainLoader.getController();
        mainController.setMain(this);
        mTree = mainController.getDbtree();
        mDetail = mainController.getDetail();
        add = mainController.getAdd();
        add.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                addField();
            }
        });
        sub = mainController.getSub();
        sub.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                subField();
            }
        });

        //region 初始化项目树
        {
            mTree.setShowRoot(true);
            mTree.setEditable(true);
            mTree.setDisable(false);
            mTree.setCellFactory(new Callback<TreeView, TreeCell>() {
                @Override
                public TreeCell call(TreeView param) {
                    TextFieldTreeCell textFieldTreeCell = new TextFieldTreeCell(new DefaultStringConverter());
                    textFieldTreeCell.setEditable(false);
                    // creating cell from deafult factory
                    TreeCell treeCell = TextFieldTreeCell.forTreeView().call(param);
                    // setting handlers
                    textFieldTreeCell.setOnDragDetected(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            TextFieldTreeCell source = (TextFieldTreeCell) event.getSource();
                            String text = source.getText();
                            Module dbByDBName = projectManager.findDBByDBName(text);
                            dragMD = dbByDBName != null;
                            if (dragMD) {
                                System.out.println("拖拽模块:" + text);
                            } else {
                                System.out.println("拖拽对象:" + text);
                            }
                            Dragboard md = source.startDragAndDrop(TransferMode.ANY);
                            ClipboardContent content = new ClipboardContent();
                            content.putString(source.getText());
                            md.setContent(content);
                            event.consume();
                        }
                    });
                    textFieldTreeCell.setOnDragOver(new EventHandler<DragEvent>() {
                        @Override
                        public void handle(DragEvent event) {
                            Dragboard md = event.getDragboard();
                            TextFieldTreeCell source = (TextFieldTreeCell) event.getSource();

                            Module dbByDBName = projectManager.findDBByDBName(source.getText());

                            if (dragMD && dbByDBName != null) {
                                double y = event.getY();
                                double height = textFieldTreeCell.getHeight();

                                if (source.getText().equals(md.getString())) {
                                    event.acceptTransferModes(TransferMode.MOVE);
                                } else if (y >= height / 4 && y < height * 3 / 4) {
                                    event.acceptTransferModes(TransferMode.MOVE);
                                }
                            }

                            if (!dragMD && dbByDBName == null) {
                                double y = event.getY();
                                double height = textFieldTreeCell.getHeight();

                                if (y >= height / 4 && y < height * 3 / 4) {
                                    event.acceptTransferModes(TransferMode.MOVE);
                                } else {
                                    event.acceptTransferModes(TransferMode.COPY);
                                }
                            }
                            event.consume();
                        }
                    });
                    textFieldTreeCell.setOnDragDropped(new EventHandler<DragEvent>() {
                        @Override
                        public void handle(DragEvent event) {
                            Dragboard md = event.getDragboard();
                            String m1 = md.getString();

                            TreeCell source = (TreeCell<String>) event.getSource();
                            String m2 = ((TreeCell<String>) event.getGestureTarget()).getItem();

                            if (dragMD) {
                                List<Module> mds = projectManager.getMds();

                                int i1 = 0, i2 = 0;
                                for (int i = 0; i < mds.size(); i++) {
                                    if (mds.get(i).getName().equals(m1)) {
                                        i1 = i;
                                    }
                                    if (mds.get(i).getName().equals(m2)) {
                                        i2 = i;
                                    }
                                }

                                if (event.getTransferMode().equals(TransferMode.COPY)) {//插入

                                } else if (event.getTransferMode().equals(TransferMode.MOVE)) {//交换
                                    Tool.exchange(mds, i1, i2);
                                }
                            } else {
                                if (currentModule != null) {
                                    int i1 = 0, i2 = 0;
                                    Table t1 = null, t2 = null;
                                    for (int i = 0; i < currentModule.getTables().size(); i++) {
                                        if (currentModule.getTables().get(i).getTableName().equals(m1)) {
                                            i1 = i;
                                            t1 = currentModule.getTables().get(i);
                                        }
                                        if (currentModule.getTables().get(i).getTableName().equals(m2)) {
                                            i2 = i;
                                            t2 = currentModule.getTables().get(i);
                                        }
                                    }
                                    if (t1 == null || t2 == null) {
                                        return;
                                    }

                                    if (event.getTransferMode().equals(TransferMode.COPY)) {//插入
                                        double y = event.getY();
                                        double height = textFieldTreeCell.getHeight();
                                        if (y < height / 2) {
                                            currentModule.getTables().add(i2, t1);
                                        } else {
                                            currentModule.getTables().add(i2 + 1, t1);
                                        }
                                        if (i1 < i2) {
                                            currentModule.getTables().remove(i1);
                                        } else {
                                            currentModule.getTables().remove(i1 + 1);
                                        }

                                    } else if (event.getTransferMode().equals(TransferMode.MOVE)) {//交换
                                        Tool.exchange(currentModule.getTables(), i1, i2);
                                    }
                                }
                            }
                            event.setDropCompleted(true);
                            event.consume();
                            mTree.getSelectionModel().clearSelection();
                            int focusedIndex = mTree.getFocusModel().getFocusedIndex();
                            System.out.println(focusedIndex);
                        }
                    });
                    return textFieldTreeCell;
                }
            });
        }
        //endregion

        //region 初始化项目面板
        {
            URL projectdetail = JavaFxApplication.class.getClassLoader().getResource("fxml/DetailProject.fxml");
            if (projectdetail == null) {
                projectdetail = getClass().getResource("../../../fxml/DetailProject.fxml");
            }
            mProjectLoader = new FXMLLoader(projectdetail);
            mProjectLoader.load();
            detailProjectController = mProjectLoader.getController();

            detailProjectController.getName().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    currentProject.setName(newValue);
                }
            });
            detailProjectController.getNote().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    currentProject.setNote(newValue);
                }
            });
            detailProjectController.getDomain().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    currentProject.setDomain(newValue);
                }
            });
            detailProjectController.getAuthor().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    currentProject.setAuthor(newValue);
                }
            });
            detailProjectController.getDatabase().selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
                @Override
                public void changed(ObservableValue<? extends Toggle> observable, Toggle oldValue, Toggle newValue) {
                    RadioButton radioButton = (RadioButton) newValue;
                    currentProject.setDatabase(DataBase.valueOf(radioButton.getText()));
                }
            });
            detailProjectController.getFrame().selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
                @Override
                public void changed(ObservableValue<? extends Toggle> observable, Toggle oldValue, Toggle newValue) {
                    RadioButton radioButton = (RadioButton) newValue;
                    currentProject.setFrame(Frame.valueOf(radioButton.getText()));
                }
            });


            detailProjectController.getNeedMordDB().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentProject.setNeedMoreDB(newValue);
                }
            });
            detailProjectController.getNeedAsync().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentProject.setNeedAsync(newValue);
                }
            });
            detailProjectController.getNeedMail().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentProject.setNeedEMail(newValue);
                }
            });
        }
        //endregion

        //region 初始化模块面板
        {
            URL mddetail = JavaFxApplication.class.getClassLoader().getResource("fxml/DetailModule.fxml");
            if (mddetail == null) {
                mddetail = getClass().getResource("../../../fxml/DetailModule.fxml");
            }
            mModuleLoader = new FXMLLoader(mddetail);
            mModuleLoader.load();
            detailModuleController = mModuleLoader.getController();
            detailModuleController.getModuleComment().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    if (currentModule != null) {
                        currentModule.setNote(newValue);
                    }
                }
            });

            detailModuleController.getModulePrefix().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    if (currentModule != null) {
                        currentModule.setModulePrefix(newValue);
                    }
                }
            });

            detailModuleController.getModuleName().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    if (currentModule != null) {
                        currentModule.setName(newValue);
                    }
                }
            });

            detailModuleController.getIsGenerate().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    if (currentModule != null) {
                        currentModule.setNeedGenerate(newValue);
                    }
                }
            });
        }
        //endregion

        //region 初始化表面板
        {
            URL tabledetail = JavaFxApplication.class.getClassLoader().getResource("fxml/DetailTable.fxml");
            if (tabledetail == null) {
                tabledetail = getClass().getResource("../../../fxml/DetailTable.fxml");
            }
            mTableLoader = new FXMLLoader(tabledetail);
            mTableLoader.load();
            detailTableController = mTableLoader.getController();

            detailTableController.getTablename().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    if (currentTable != null) {
                        currentTable.setTableName(newValue);
                    }
                }
            });
            detailTableController.getTablecomment().textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    if (currentTable != null) {
                        currentTable.setTableComment(newValue);
                    }
                }
            });
            detailTableController.getSys().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setSys(newValue);
                }
            });
            detailTableController.getAjax().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setAjax(newValue);
                }
            });
            detailTableController.getApi().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setApi(newValue);
                }
            });
            detailTableController.getMsvr().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setMsvr(newValue);
                }
            });
            detailTableController.getPage().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setPage(newValue);
                    if (newValue) {
                        detailTableController.getPageAdd().setSelected(true);
                        detailTableController.getPageImp().setSelected(true);
                        detailTableController.getPageExp().setSelected(true);
                    } else {
                        detailTableController.getPageAdd().setSelected(false);
                        detailTableController.getPageImp().setSelected(false);
                        detailTableController.getPageExp().setSelected(false);
                    }
                }
            });
            detailTableController.getPageAdd().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setPageAdd(newValue);
                }
            });
            detailTableController.getPageDel().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setPageDel(newValue);
                }
            });
            detailTableController.getPageExp().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setPageExp(newValue);
                }
            });
            detailTableController.getPageImp().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setPageImp(newValue);
                }
            });
            detailTableController.getCreate().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setCreate(newValue);
                    if (!currentTable.needMgr()) {
                        detailTableController.getAjax().setSelected(false);
                    }
                }
            });
            detailTableController.getDelete().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setDelete(newValue);
                    if (!currentTable.needMgr()) {
                        detailTableController.getAjax().setSelected(false);
                    }
                }
            });
            detailTableController.getUpdate().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setUpdate(newValue);
                    if (!currentTable.needMgr()) {
                        detailTableController.getAjax().setSelected(false);
                    }
                }
            });
            detailTableController.getFind().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setFind(newValue);
                    if (!currentTable.needMgr()) {
                        detailTableController.getAjax().setSelected(false);
                    }
                }
            });
            detailTableController.getGet().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setGet(newValue);
                    if (!currentTable.needMgr()) {
                        detailTableController.getAjax().setSelected(false);
                    }
                }
            });
            detailTableController.getSearch().selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    currentTable.setSearch(newValue);
                    if (!currentTable.needMgr()) {
                        detailTableController.getAjax().setSelected(false);
                    }
                }
            });
            detailTableController.getAdd().setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    Dialog.showMethodInput("新增业务", "请输入:", new Dialog.InputMethodCall() {
                        @Override
                        public void call(String name, String note) {
                            if (name.matches("create|delete|update|find|get|search")) {
                                Dialog.showYesNo("已经存在的基础业务方法！");
                                return;
                            }

                            for (Node node : detailTableController.getMethods().getChildren()) {
                                if (node instanceof CheckBox) {
                                    CheckBox checkBox = (CheckBox) node;

                                    if (name.equals(checkBox.getText())) {
                                        Dialog.showYesNo("已经存在的业务方法！");
                                        return;
                                    }
                                }
                            }
                            TableMethod method = new TableMethod(name, note, true);
                            CheckBox checkBox = new CheckBox(name);
                            checkBox.setSelected(true);
                            checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
                                @Override
                                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                                    for (TableMethod tableMethod : currentTable.getMethods()) {
                                        if (tableMethod.getName().equals(checkBox.getText())) {
                                            tableMethod.setSelected(newValue);
                                        }
                                    }
                                }
                            });

                            ContextMenu contextMenu = new ContextMenu(new MenuItem("删除"));
                            contextMenu.setOnAction(new EventHandler<ActionEvent>() {
                                @Override
                                public void handle(ActionEvent event) {
                                    detailTableController.getMethods().getChildren().remove(checkBox);
                                    currentTable.getMethods().remove(method);
                                }
                            });
                            checkBox.setContextMenu(contextMenu);

                            int size = detailTableController.getMethods().getChildren().size();
                            detailTableController.getMethods().getChildren().add(size - 1, checkBox);
                            currentTable.getMethods().add(method);
                        }
                    });
                }
            });
        }
        //endregion

        //region 初始化字段面板
        {

            mFields = mainController.getFields();
            mFields.setEditable(true);
            mFields.setSortPolicy(new Callback<TableView, Boolean>() {
                @Override
                public Boolean call(TableView param) {
                    //禁止点击列头排序
                    return false;
                }
            });
            mFields.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    int selectedIndex = mFields.getSelectionModel().getSelectedIndex();
                    if (currentTable == null || selectedIndex == -1) {
                        return;
                    }
                    Field field = currentTable.getFields().get(selectedIndex);
                    ContextMenuBuilder builder = new ContextMenuBuilder();
                    builder.add("新增", new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent event) {
                            addField();
                        }
                    });
                    builder.add("删除", new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent event) {
                            subField();
                        }
                    });
                    if (field.getFieldType().equals(FieldType.Dict.name())) {
                        builder.add("编辑字典", new EventHandler<ActionEvent>() {
                            @Override
                            public void handle(ActionEvent event) {
                                MenuItem target = (MenuItem) event.getTarget();
                                int index = mFields.getSelectionModel().getSelectedIndex();
                                List<Field> fields = currentTable.getFields();
                                Field field = fields.get(index);
                                Dialog.showSelectEdit(field);
                            }
                        });
                    } else if (field.getFieldType().equals(FieldType.Select.name())) {
                        builder.add("编辑选项", new EventHandler<ActionEvent>() {
                            @Override
                            public void handle(ActionEvent event) {
                                int index = mFields.getSelectionModel().getSelectedIndex();
                                List<Field> fields = currentTable.getFields();
                                Field field = fields.get(index);
                                Dialog.showSelectEdit(field);
                            }
                        });
                    } else if (field.getFieldType().equals(FieldType.Boolean.name())) {
                        builder.add("编辑是否", new EventHandler<ActionEvent>() {
                            @Override
                            public void handle(ActionEvent event) {
                                int index = mFields.getSelectionModel().getSelectedIndex();
                                List<Field> fields = currentTable.getFields();
                                Field field = fields.get(index);
                                if (field.getSelectItems().size() == 2) {

                                } else {
                                    {
                                        SelectItem selectItem = new SelectItem();
                                        selectItem.setValue("true");
                                        selectItem.setLabel("是");
                                        field.getSelectItems().add(selectItem);
                                    }
                                    {
                                        SelectItem selectItem = new SelectItem();
                                        selectItem.setValue("false");
                                        selectItem.setLabel("否");
                                        field.getSelectItems().add(selectItem);
                                    }

                                }
                                Dialog.showSelectEdit(field);
                            }
                        });
                    }
                    builder.add("向上调整", new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent event) {
                            int index = mFields.getSelectionModel().getSelectedIndex();
                            List<Field> fields = currentTable.getFields();
                            if (index > 0) {
                                fields.add(index - 1, fields.get(index));
                                fields.add(index + 1, fields.get(index));
                                fields.remove(index);
                                fields.remove(index + 1);
                            }
                        }
                    });
                    builder.add("向下调整", new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent event) {
                            int index = mFields.getSelectionModel().getSelectedIndex();
                            List<Field> fields = currentTable.getFields();
                            if (index < fields.size() - 1) {
                                fields.add(index, fields.get(index + 1));
                                fields.add(index + 2, fields.get(index + 1));
                                fields.remove(index + 1);
                                fields.remove(index + 2);
                            }
                        }
                    });
                    ContextMenu con = builder.build();
                    mFields.setContextMenu(con);
                }
            });

        }
        //endregion

        // 尝试加载一个项目树，project文件夹有则默认加载第一个，否则创建一个新项目树
        initProjectTree(projectManager.invalidate());
        super.init();
    }

    private void addField() {
        if (currentTable != null && mFields != null) {
            List<Field> fields = currentTable.getFields();
            int i = projectManager.getNewFieldName(fields);
            Field field = fields.get(i);
            System.out.println("新增字段-" + field.getFieldName() + "成功!");
            this.mFields.getSelectionModel().select(i);
            this.mFields.getFocusModel().focus(i);
        }
    }

    private void subField() {
        if (currentTable != null) {
            int selectedIndex = mFields.getSelectionModel().getSelectedIndex();
            if (selectedIndex > -1 && !currentTable.getFields().get(selectedIndex).getIsSystem()) {
                currentTable.getFields().remove(selectedIndex);
                mFields.getSelectionModel().clearSelection();
            }

        }
    }

    public void initProjectTree(Project project) {
        currentProject = project;
        TreeItem<Project> projectTreeItem = new TreeItem<Project>(currentProject);
        mTree.setRoot(projectTreeItem);
        projectTreeItem.setExpanded(true);
        for (Module module : currentProject.getModules()) {
            TreeItem moduleTreeItem = new TreeItem(module);
            moduleTreeItem.setExpanded(true);
            projectTreeItem.getChildren().add(moduleTreeItem);
            for (Table table : module.getTables()) {
                TreeItem tableTreeItem = new TreeItem(table);
                moduleTreeItem.getChildren().add(tableTreeItem);
                tableTreeItem.setExpanded(true);
            }
        }
        mTree.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                TreeItem model = (TreeItem) mTree.getSelectionModel().getSelectedItem();
                if (model == null) {
                    return;
                }
                Object value = model.getValue();
                if (value instanceof Project) {
                    loadProject();
                } else if (value instanceof Module) {
                    currentModule = (Module) value;
                    loadModule();
                } else if (value instanceof Table) {
                    currentTable = (Table) value;
                    initTable();
                }
            }
        });

        mTree.setCellFactory(new Callback<TreeView, TreeCell>() {
            @Override
            public TreeCell call(TreeView param) {
                return new TreeCell() {
                    @Override
                    protected void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                        if (empty) {
                            setText(null);
                            setGraphic(null);
                            return;
                        }
                        if (isEditing()) {
                            return;
                        }

                        if (item instanceof Project) {
                            Project ex = (Project) item;
                            setText(ex.getName());
                            ex.nameProperty().addListener(new ChangeListener<String>() {
                                @Override
                                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                                    setText(ex.getName());
                                }
                            });

                            setContextMenu(new ContextMenuBuilder()
                                    .add("新增模块", new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent event) {
                                            Module module = projectManager.newModule();
                                            TreeItem moduleTreeItem = new TreeItem(module);
                                            moduleTreeItem.setExpanded(true);
                                            getTreeItem().getChildren().add(moduleTreeItem);
                                            System.out.println("新增模块" + module.getName());
                                        }
                                    }).build());
                        } else if (item instanceof Module) {
                            Module mo = (Module) item;
                            setText(mo.getName());
                            mo.nameProperty().addListener(new ChangeListener<String>() {
                                @Override
                                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                                    setText(mo.getName());
                                }
                            });
                            //region 模块右击菜单
                            setContextMenu(new ContextMenuBuilder()
                                    .add("新增对象", new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent event) {
                                            Module module = (Module) getTreeItem().getValue();
                                            Table table = projectManager.newTable(module);
                                            TreeItem tableTreeItem = new TreeItem(table);
                                            tableTreeItem.setExpanded(true);
                                            getTreeItem().getChildren().add(tableTreeItem);
                                            System.out.println("新增对象" + table.getTableName());
                                        }
                                    })
                                    .add("删除模块", new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent event) {
                                            TreeItem projectTreeItem = getTreeItem().getParent();
                                            Project project = (Project) getTreeItem().getParent().getValue();
                                            TreeItem moduleTreeItem = getTreeItem();
                                            Module module = (Module) getTreeItem().getValue();

                                            projectTreeItem.getChildren().remove(moduleTreeItem);
                                            project.getModules().remove(module);
                                            if (currentModule.hashCode() == module.hashCode()) {
                                                loadProject();
                                            }
                                            System.out.println("删除模块" + mo.getName());
                                        }
                                    })
                                    .add("向上调整", new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent event) {
                                            TreeItem projectTreeItem = getTreeItem().getParent();
                                            Project project = (Project) getTreeItem().getParent().getValue();
                                            Module module = (Module) getTreeItem().getValue();
                                            int indexOf = project.getModules().indexOf(module);
                                            if (indexOf > 0) {
                                                Tool.exchange(projectTreeItem.getChildren(), indexOf - 1, indexOf);
                                                Tool.exchange(project.getModules(), indexOf - 1, indexOf);
                                                System.out.println("向上调整" + mo.getName());
                                            }
                                        }
                                    })
                                    .add("向下调整", new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent event) {
                                            TreeItem projectTreeItem = getTreeItem().getParent();
                                            Project project = (Project) getTreeItem().getParent().getValue();
                                            Module module = (Module) getTreeItem().getValue();
                                            int indexOf = project.getModules().indexOf(module);
                                            if (indexOf < project.getModules().size() - 1) {
                                                Tool.exchange(projectTreeItem.getChildren(), indexOf, indexOf + 1);
                                                Tool.exchange(project.getModules(), indexOf, indexOf + 1);
                                                System.out.println("向下调整" + mo.getName());
                                            }
                                        }
                                    }).build());
                            //endregion
                        } else if (item instanceof Table) {
                            Table ta = (Table) item;
                            setText(ta.getTableName());
                            ta.tableNameProperty().addListener(new ChangeListener<String>() {
                                @Override
                                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                                    setText(ta.getTableName());
                                }
                            });
                            setContextMenu(new ContextMenuBuilder()
                                    .add("删除对象", new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent event) {
                                            Module module = (Module) getTreeItem().getParent().getValue();
                                            Table table = (Table) getTreeItem().getValue();
                                            int indexOf = module.getTables().indexOf(table);

                                            getTreeItem().getParent().getChildren().remove(indexOf);
                                            module.getTables().remove(indexOf);
                                            if (currentTable.hashCode() == table.hashCode()) {
                                                loadModule();
                                            }
                                            System.out.println("删除对象" + table.getTableName());
                                        }
                                    })
                                    .add("向上调整", new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent event) {
                                            TreeItem moduleTreeItem = getTreeItem().getParent();
                                            Module module = (Module) getTreeItem().getParent().getValue();
                                            Table table = (Table) getTreeItem().getValue();
                                            int indexOf = module.getTables().indexOf(table);
                                            if (indexOf > 0) {
                                                Tool.exchange(moduleTreeItem.getChildren(), indexOf - 1, indexOf);
                                                Tool.exchange(module.getTables(), indexOf - 1, indexOf);
                                                System.out.println("向上调整" + table.getTableName());
                                            }
                                        }
                                    })
                                    .add("向下调整", new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent event) {
                                            TreeItem moduleTreeItem = getTreeItem().getParent();
                                            Module module = (Module) getTreeItem().getParent().getValue();
                                            Table table = (Table) getTreeItem().getValue();
                                            int indexOf = module.getTables().indexOf(table);
                                            if (indexOf < module.getTables().size() - 1) {
                                                Tool.exchange(moduleTreeItem.getChildren(), indexOf, indexOf + 1);
                                                Tool.exchange(module.getTables(), indexOf, indexOf + 1);
                                                System.out.println("向下调整" + table.getTableName());
                                            }
                                        }
                                    }).build());
                        }

                    }
                };
            }
        });
    }

    private void loadModule() {
        if (currentModule == null) {
            return;
        }

        GridPane gridPane = mModuleLoader.getRoot();
        detailModuleController.getModuleComment().setText(currentModule.getNote());
        detailModuleController.getModulePrefix().setText(currentModule.getModulePrefix());
        detailModuleController.getModuleName().setText(currentModule.getName());
        detailModuleController.getIsGenerate().setSelected(currentModule.getNeedGenerate());

        if (gridPane != null) {
            mDetail.getChildren().clear();
            mDetail.getChildren().add(gridPane);
        }
        if (mFields != null && mFields.getItems() != null) {
            mFields.setItems(null);
        }
    }

    public void loadProject() {
        GridPane gridPane = mProjectLoader.getRoot();
        detailProjectController.getName().setText(currentProject.getName());
        detailProjectController.getNote().setText(currentProject.getNote());
        detailProjectController.getDomain().setText(currentProject.getDomain());
        detailProjectController.getAuthor().setText(currentProject.getAuthor());
        ObservableList<Toggle> toggles = detailProjectController.getDatabase().getToggles();
        for (Toggle tog : toggles) {
            RadioButton radioButton = (RadioButton) tog;
            if (radioButton.getText().equals(currentProject.getDatabase().name())) {
                radioButton.setSelected(true);
            }
        }

        ObservableList<Toggle> getAuto = detailProjectController.getFrame().getToggles();
        for (Toggle toggle : getAuto) {
            RadioButton radioButton = (RadioButton) toggle;
            if (radioButton.getText().equals(currentProject.getFrame().name())) {
                radioButton.setSelected(true);
            }
        }
        detailProjectController.getNeedMordDB().setSelected(currentProject.isNeedMoreDB());
        detailProjectController.getNeedAsync().setSelected(currentProject.isNeedAsync());
        detailProjectController.getNeedMail().setSelected(currentProject.isNeedEMail());

        if (gridPane != null) {
            mDetail.getChildren().clear();
            mDetail.getChildren().add(gridPane);
        }
        if (mFields != null && mFields.getItems() != null) {
            mFields.setItems(null);
        }
    }

    /**
     * 加载表对象面板
     */
    private void initTable() {
        GridPane gridPane = mTableLoader.getRoot();
        if (currentTable != null) {
            detailTableController.getTablename().setText(currentTable.getTableName());
            detailTableController.getTablecomment().setText(currentTable.getTableComment());
            detailTableController.getCreate().setSelected(currentTable.getCreate());
            detailTableController.getDelete().setSelected(currentTable.getDelete());
            detailTableController.getUpdate().setSelected(currentTable.getUpdate());
            detailTableController.getFind().setSelected(currentTable.getFind());
            detailTableController.getGet().setSelected(currentTable.getGet());
            detailTableController.getSearch().setSelected(currentTable.getSearch());
            detailTableController.getSys().setSelected(currentTable.getSys());
            detailTableController.getAjax().setSelected(currentTable.isAjax());
            detailTableController.getPage().setSelected(currentTable.isPage());
            detailTableController.getPageAdd().setSelected(currentTable.isPageAdd());
            detailTableController.getPageDel().setSelected(currentTable.isPageDel());
            detailTableController.getPageImp().setSelected(currentTable.isPageImp());
            detailTableController.getPageExp().setSelected(currentTable.isPageExp());
            detailTableController.getApi().setSelected(currentTable.getApi());
            detailTableController.getMsvr().setSelected(currentTable.getMsvr());

            for (TableMethod method : currentTable.getMethods()) {
                CheckBox checkBox = new CheckBox(method.getName());
                checkBox.setSelected(method.isSelected());
                checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        for (TableMethod tableMethod : currentTable.getMethods()) {
                            if (tableMethod.getName().equals(checkBox.getText())) {
                                tableMethod.setSelected(newValue);
                            }
                        }
                    }
                });
                ContextMenu contextMenu = new ContextMenu(new MenuItem("删除"));
                contextMenu.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent event) {
                        detailTableController.getMethods().getChildren().remove(checkBox);
                        currentTable.getMethods().remove(method);
                    }
                });
                checkBox.setContextMenu(contextMenu);

                int size = detailTableController.getMethods().getChildren().size();
                detailTableController.getMethods().getChildren().add(size - 1, checkBox);
            }
        }

        if (gridPane != null) {
            mDetail.getChildren().clear();
            mDetail.getChildren().add(gridPane);
        }
        ObservableList<TableColumn> columns = mFields.getColumns();

        columns.get(0).setCellValueFactory(new PropertyValueFactory<Field, String>("fieldName"));
        columns.get(0).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new DefaultStringConverter()) {

                    @Override
                    public void commitEdit(Object newValue) {
                        int row = this.getTableRow().getIndex();
                        Field field = currentTable.getFields().get(row);

                        // 驼峰转下划线
                        String newValue_ = (String) newValue;
                        if (mainController.getMcdx().isSelected()) {
                            newValue_ = Tool.any2Underline(newValue_);
                        }

                        // 检查是否重复
                        List<Integer> integers = new ArrayList<>();
                        for (int i = 0; i < currentTable.getFields().size(); i++) {
                            if (currentTable.getFields().get(i).getFieldName().equals(newValue)) {
                                integers.add(i);
                            }
                        }
                        if (integers.size() > 1) {
                            Dialog.showYesNo("警告", String.format(Locale.CHINA, "存在多个[%s]", newValue));
                            return;
                        } else if (integers.size() == 1 && row != integers.get(0)) {
                            Dialog.showYesNo("警告", String.format(Locale.CHINA, "已经存在[%s]", newValue));
                            return;
                        }

                        // 字典类型智能关联
                        field.setFieldName(newValue_);
                        if (newValue_.toUpperCase().endsWith("_ID")) {
                            field.setFieldType(FieldType.Long.name());
                        }
                        if (newValue_.toUpperCase().endsWith("_TIME") || newValue_.toUpperCase().endsWith("_DATE")) {
                            field.setFieldType(FieldType.Date.name());
                        }
                        if (newValue_.toUpperCase().endsWith("_TYPE")) {
                            field.setFieldType(FieldType.Select.name());
                        }
                        super.commitEdit(newValue_);
                    }

                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                        if (currentTable != null) {
                            int index = this.getTableRow().getIndex();
                            if (index >= 0 && index <= currentTable.getFields().size() - 1) {
                                Field field = currentTable.getFields().get(index);
                                if (field.getIsSystem()) {
                                    ignoreField(this);
                                    this.setDisable(true);
                                } else {
                                    recoveryField(this);
                                    this.setDisable(false);
                                }
                            }
                        }
                    }
                };
                textFieldTableCell.setOnDragDetected(new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent event) {
                        TableCell source = (TableCell) event.getSource();
                        Dragboard md = source.startDragAndDrop(TransferMode.ANY);
                        ClipboardContent content = new ClipboardContent();
                        content.putString((String) source.getItem());
                        md.setContent(content);
                        event.consume();
                    }
                });
                textFieldTableCell.setOnDragOver(new EventHandler<DragEvent>() {
                    @Override
                    public void handle(DragEvent event) {
                        Dragboard md = event.getDragboard();

                        if (md.hasString()) {
                            double y = event.getY();
                            double height = textFieldTableCell.getHeight();

                            if (y >= height / 4 && y < height * 3 / 4) {
                                event.acceptTransferModes(TransferMode.MOVE);
                            } else {
                                event.acceptTransferModes(TransferMode.COPY);
                            }
                        }
                        event.consume();
                    }
                });
                textFieldTableCell.setOnDragDropped(new EventHandler<DragEvent>() {
                    @Override
                    public void handle(DragEvent event) {
                        Dragboard md = event.getDragboard();
                        String f1 = md.getString();

                        TableCell source = (TableCell) event.getSource();
                        String f2 = ((TableCell) event.getGestureTarget()).getText();

                        if (currentTable != null) {
                            int i1 = 0, i2 = 0;
                            Field t1 = null, t2 = null;
                            for (int i = 0; i < currentTable.getFields().size(); i++) {
                                if (currentTable.getFields().get(i).getFieldName().equals(f1)) {
                                    i1 = i;
                                    t1 = currentTable.getFields().get(i);
                                }
                                if (currentTable.getFields().get(i).getFieldName().equals(f2)) {
                                    i2 = i;
                                    t2 = currentTable.getFields().get(i);
                                }
                            }

                            if (event.getTransferMode().equals(TransferMode.COPY)) {//插入
                                double y = event.getY();
                                double height = textFieldTableCell.getHeight();

                                if (y < height / 2) {
                                    currentTable.getFields().add(i2, t1);
                                } else {
                                    currentTable.getFields().add(i2 + 1, t1);
                                }
                                if (i1 < i2) {
                                    currentTable.getFields().remove(i1);
                                } else {
                                    currentTable.getFields().remove(i1 + 1);
                                }

                            } else if (event.getTransferMode().equals(TransferMode.MOVE)) {//交换
                                currentTable.getFields().add(i1, t2);
                                currentTable.getFields().remove(i1 + 1);
                                currentTable.getFields().add(i2, t1);
                                currentTable.getFields().remove(i2 + 1);
                            }
                        }
                        event.setDropCompleted(true);
                        event.consume();
                    }
                });
                return textFieldTableCell;
            }
        });
        columns.get(1).setCellValueFactory(new PropertyValueFactory("fieldType"));
        columns.get(1).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                ObservableList<String> objects = FXCollections.observableArrayList();

                Class clz = FieldType.class;
                for (Object obj : clz.getEnumConstants()) {
                    if (obj instanceof FieldType) {
                        objects.add(obj.toString());
                    }
                }
                ChoiceBoxTableCell choiceBoxTableCell = new ChoiceBoxTableCell(objects) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                        if (currentTable != null) {
                            int index = this.getTableRow().getIndex();
                            if (index >= 0 && index <= currentTable.getFields().size() - 1) {
                                Field field = currentTable.getFields().get(index);
                                FieldType fieldType = FieldType.parse(field.getFieldType());
                                if (fieldType.isFix() && fieldType.getDefaultLength() != field.getFieldLength()) {
                                    field.setFieldLength(fieldType.getDefaultLength());
                                }
                                if (!field.getFieldType().contains("String_var")) {
                                    field.setIsLike(false);
                                }
                                if (field.getIsSystem()) {
                                    ignoreField(this);
                                    this.setDisable(true);
                                } else {
                                    recoveryField(this);
                                    this.setDisable(false);
                                }
                            }
                        }
                    }
                };

                param.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent event) {
                        int row = event.getTablePosition().getRow();
                        Field field = currentTable.getFields().get(row);
                        String fieldType = (String) event.getNewValue();
                        field.setFieldLength(FieldType.parse(fieldType).getDefaultLength());
                        field.setFieldType(fieldType);
                        field.getSelectItems().clear();
                        mFields.refresh();
                    }
                });
                return choiceBoxTableCell;
            }
        });
        columns.get(2).setCellValueFactory(new PropertyValueFactory("fieldLength"));
        columns.get(2).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                param.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent event) {
                        int row = event.getTablePosition().getRow();
                        Field field = currentTable.getFields().get(row);
                        Set<String> set = new HashSet<>();
                        set.add("String_var");
                        set.add("String_super");
                        set.add("Dict");
                        set.add("Select");
                        if (set.contains(field.getFieldType())) {
                            try {
                                field.setFieldLength((Integer) event.getNewValue());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        mFields.refresh();
                    }
                });
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new IntegerStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                        if (currentTable != null) {
                            int index = this.getTableRow().getIndex();
                            if (index >= 0 && index <= currentTable.getFields().size() - 1) {
                                Field field = currentTable.getFields().get(index);
                                if (field.getIsSystem()) {
                                    ignoreField(this);
                                    this.setDisable(true);
                                } else if (FieldType.parse(field.getFieldType()).isFix()) {
                                    ignoreField(this);
                                    this.setDisable(true);
                                } else {
                                    recoveryField(this);
                                    this.setDisable(false);
                                }
                            }
                        }
                    }
                };
                return textFieldTableCell;
            }
        });
        columns.get(3).setCellValueFactory(new PropertyValueFactory("defaultValue"));
        columns.get(3).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                param.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent event) {
                        int row = event.getTablePosition().getRow();
                        Field field = currentTable.getFields().get(row);
                        field.setDefaultValue((String) event.getNewValue());
                    }
                });
                return new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                        if (currentTable != null) {
                            int index = this.getTableRow().getIndex();
                            if (index >= 0 && index <= currentTable.getFields().size() - 1) {
                                Field field = currentTable.getFields().get(index);
                                if (field.getIsSystem()) {
                                    ignoreField(this);
                                    this.setDisable(true);
                                } else {
                                    recoveryField(this);
                                    this.setDisable(false);
                                }
                            }
                        }
                    }
                };
            }
        });
        columns.get(4).setCellValueFactory(new PropertyValueFactory("isPrimaryKey"));
        columns.get(4).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                DBCheckBoxTableCell checkBoxTableCell = new DBCheckBoxTableCell();

                DBCheckBoxTableCell.sCallback sCallback = checkBoxTableCell.new sCallback() {
                    @Override
                    public ObservableValue<Boolean> call(Integer param) {
                        super.call(param);
                        List<Field> fields = currentTable.getFields();

                        if (fields.get(param).getIsSystem()) {
                            checkBoxTableCell.setInvalid(true);
                        } else {
                            checkBoxTableCell.setInvalid(false);
                        }
                        if (fields.get(param).getIsPrimaryKey()) {
                            return new SimpleBooleanProperty(true);
                        } else {
                            return new SimpleBooleanProperty(false);
                        }
                    }
                };
                checkBoxTableCell.setSelectedStateCallback(sCallback);
                checkBoxTableCell.setOnChangeListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        int param1 = checkBoxTableCell.getParam();
                        Field field = currentTable.getFields().get(param1);
                        field.setIsPrimaryKey(newValue);
                    }
                });
                return checkBoxTableCell;
            }
        });
        columns.get(5).setCellValueFactory(new PropertyValueFactory("isMust"));
        columns.get(5).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                final DBCheckBoxTableCell checkBoxTableCell = new DBCheckBoxTableCell();
                DBCheckBoxTableCell.sCallback sCallback = checkBoxTableCell.new sCallback() {
                    @Override
                    public ObservableValue<Boolean> call(Integer param) {
                        super.call(param);
                        List<Field> fields = currentTable.getFields();
                        if (fields.get(param).getIsSystem()) {
                            checkBoxTableCell.setInvalid(true);
                        } else {
                            checkBoxTableCell.setInvalid(false);
                        }
                        if (fields.get(param).getIsMust()) {
                            return new SimpleBooleanProperty(true);
                        } else {
                            return new SimpleBooleanProperty(false);
                        }
                    }
                };
                checkBoxTableCell.setSelectedStateCallback(sCallback);
                checkBoxTableCell.setOnChangeListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        int param1 = checkBoxTableCell.getParam();
                        Field field = currentTable.getFields().get(param1);
                        field.setIsMust(newValue);
                    }
                });
                return checkBoxTableCell;
            }
        });
        columns.get(6).setCellValueFactory(new PropertyValueFactory("isUnique"));
        columns.get(6).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                final DBCheckBoxTableCell checkBoxTableCell = new DBCheckBoxTableCell();
                DBCheckBoxTableCell.sCallback sCallback = checkBoxTableCell.new sCallback() {
                    @Override
                    public ObservableValue<Boolean> call(Integer param) {
                        super.call(param);
                        List<Field> fields = currentTable.getFields();
                        if (fields.get(param).getIsSystem()) {
                            checkBoxTableCell.setInvalid(true);
                        } else {
                            checkBoxTableCell.setInvalid(false);
                        }
                        if (fields.get(param).getIsUnique()) {
                            return new SimpleBooleanProperty(true);
                        } else {
                            return new SimpleBooleanProperty(false);
                        }
                    }
                };
                checkBoxTableCell.setSelectedStateCallback(sCallback);
                checkBoxTableCell.setOnChangeListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        int param1 = checkBoxTableCell.getParam();
                        Field field = currentTable.getFields().get(param1);
                        field.setIsUnique(newValue);

                        if (newValue) {//
                            field.setIsQuery(true);
                        }
                    }
                });
                return checkBoxTableCell;
            }
        });
        columns.get(7).setCellValueFactory(new PropertyValueFactory("isQuery"));
        columns.get(7).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                final DBCheckBoxTableCell checkBoxTableCell = new DBCheckBoxTableCell();
                DBCheckBoxTableCell.sCallback sCallback = checkBoxTableCell.new sCallback() {
                    @Override
                    public ObservableValue<Boolean> call(Integer param) {
                        super.call(param);
                        List<Field> fields = currentTable.getFields();
                        if (fields.get(param).getIsSystem()) {
                            checkBoxTableCell.setInvalid(true);
                        } else {
                            checkBoxTableCell.setInvalid(false);
                        }
                        if (fields.get(param).getIsQuery()) {
                            return new SimpleBooleanProperty(true);
                        } else {
                            return new SimpleBooleanProperty(false);
                        }
                    }
                };
                checkBoxTableCell.setSelectedStateCallback(sCallback);
                checkBoxTableCell.setOnChangeListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        int param1 = checkBoxTableCell.getParam();
                        Field field = currentTable.getFields().get(param1);
                        field.setIsQuery(newValue);
                        if (!newValue) {
                            field.setIsUnique(false);
                        }
                    }
                });
                return checkBoxTableCell;
            }
        });
        columns.get(8).setCellValueFactory(new PropertyValueFactory("isLike"));
        columns.get(8).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                final DBCheckBoxTableCell checkBoxTableCell = new DBCheckBoxTableCell();
                DBCheckBoxTableCell.sCallback sCallback = checkBoxTableCell.new sCallback() {
                    @Override
                    public ObservableValue<Boolean> call(Integer param) {
                        super.call(param);
                        List<Field> fields = currentTable.getFields();
                        if (fields.get(param).getIsSystem() || !fields.get(param).getFieldType().contains("String_var")) {
                            checkBoxTableCell.setInvalid(true);
                        } else {
                            checkBoxTableCell.setInvalid(false);
                        }
                        if (fields.get(param).getIsLike()) {
                            return new SimpleBooleanProperty(true);
                        } else {
                            return new SimpleBooleanProperty(false);
                        }
                    }
                };
                checkBoxTableCell.setSelectedStateCallback(sCallback);
                checkBoxTableCell.setOnChangeListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        int param1 = checkBoxTableCell.getParam();
                        Field field = currentTable.getFields().get(param1);
                        field.setIsLike(newValue);
                    }
                });
                return checkBoxTableCell;
            }
        });
        columns.get(9).setCellValueFactory(new PropertyValueFactory("isSearch"));
        columns.get(9).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                final DBCheckBoxTableCell checkBoxTableCell = new DBCheckBoxTableCell();
                DBCheckBoxTableCell.sCallback sCallback = checkBoxTableCell.new sCallback() {
                    @Override
                    public ObservableValue<Boolean> call(Integer param) {
                        super.call(param);
                        List<Field> fields = currentTable.getFields();
                        if (fields.get(param).getIsSystem()) {
                            checkBoxTableCell.setInvalid(true);
                        } else {
                            checkBoxTableCell.setInvalid(false);
                        }
                        if (fields.get(param).getIsSearch()) {
                            return new SimpleBooleanProperty(true);
                        } else {
                            return new SimpleBooleanProperty(false);
                        }
                    }
                };
                checkBoxTableCell.setSelectedStateCallback(sCallback);
                checkBoxTableCell.setOnChangeListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        int param1 = checkBoxTableCell.getParam();
                        Field field = currentTable.getFields().get(param1);
                        field.setIsSearch(newValue);
                    }
                });
                return checkBoxTableCell;
            }
        });
        columns.get(10).setCellValueFactory(new PropertyValueFactory("fieldComment"));
        columns.get(10).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {

                param.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent event) {
                        int row = event.getTablePosition().getRow();
                        Field field = currentTable.getFields().get(row);
                        field.setFieldComment((String) event.getNewValue());
                    }
                });
                return new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                        if (currentTable != null) {
                            int index = this.getTableRow().getIndex();
                            if (index >= 0 && index <= currentTable.getFields().size() - 1) {
                                Field field = currentTable.getFields().get(index);
                                if (field.getIsSystem()) {
                                    ignoreField(this);
                                    this.setDisable(true);
                                } else {
                                    recoveryField(this);
                                    this.setDisable(false);
                                }
                            }
                        }
                    }
                };
            }
        });

        if (currentTable != null) {
            ObservableList<Field> fields = currentTable.getFields();
            mFields.setItems(fields);
        }

    }

    void ignoreField(TableCell tableCell) {
        tableCell.setTextFill(Color.gray(0.8));
    }

    void recoveryField(TableCell tableCell) {
        tableCell.setTextFill(Color.BLACK);
    }

    public static void main(String[] args) {
        launch(args);
    }
}
